package com.fzhucc.modules.expert.service.impl;

import com.fzhucc.exception.BadRequestException;
import com.fzhucc.modules.expert.domain.Expert;
import com.fzhucc.modules.expert.domain.ExpertConsultationConfig;
import com.fzhucc.modules.expert.domain.dto.*;
import com.fzhucc.modules.expert.repository.ExpertConsultationConfigRepository;
import com.fzhucc.modules.expert.repository.ExpertRepository;
import com.fzhucc.modules.expert.service.ExpertConsultationConfigService;
import com.fzhucc.modules.expert.service.mapstruct.ExpertConsultationConfigMapper;
import com.fzhucc.utils.FileUtil;
import com.fzhucc.utils.PageUtil;
import com.fzhucc.utils.QueryHelp;
import com.fzhucc.utils.ValidationUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @author yyg
 * @description 服务实现
 * @date 2023-10-20
 **/
@Service
@RequiredArgsConstructor
public class ExpertConsultationConfigServiceImpl implements ExpertConsultationConfigService {

    private final ExpertConsultationConfigRepository expertConsultationConfigRepository;
    private final ExpertConsultationConfigMapper expertConsultationConfigMapper;

    private final ExpertRepository expertRepository;

    @Override
    public Map<String, Object> queryAll(ExpertConsultationConfigQueryCriteria criteria, Pageable pageable) {
        criteria.setIsDelete(0);
        Page<ExpertConsultationConfig> page = expertConsultationConfigRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(expertConsultationConfigMapper::toDto));
    }

    @Override
    public List<ExpertConsultationConfigDto> queryAll(ExpertConsultationConfigQueryCriteria criteria) {
        criteria.setIsDelete(0);
        return expertConsultationConfigMapper.toDto(expertConsultationConfigRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public ExpertConsultationConfigDto findById(Integer id) {
        ExpertConsultationConfig expertConsultationConfig = expertConsultationConfigRepository.findById(id).orElseGet(ExpertConsultationConfig::new);
        ValidationUtil.isNull(expertConsultationConfig.getId(), "ExpertConsultationConfig", "id", id);
        return expertConsultationConfigMapper.toDto(expertConsultationConfig);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ExpertConsultationConfig> create(ExpertConsultationConfigAddDto dto) {
        List<ExpertConsultationConfig> result = new ArrayList<ExpertConsultationConfig>();
        Integer expertId = dto.getExpertId();
        Optional<Expert> res = expertRepository.findById(expertId);
        if (!res.isPresent()) {
            throw new BadRequestException("专家未找到");
        }
        List<List<String>> list = dto.getList();
        if (list != null && list.size() > 0) {
            for (List<String> l : list) {
                if (l.size() == 2) {
                    ExpertConsultationConfig expertConsultationConfig = new ExpertConsultationConfig();
                    expertConsultationConfig.setExpertId(expertId);
                    expertConsultationConfig.setTimeSlot(l.get(0) + ";" + l.get(1));
                    expertConsultationConfig.setIsDelete(0);
                    ExpertConsultationConfig ops = expertConsultationConfigRepository.save(expertConsultationConfig);
                    result.add(ops);
                }
            }
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ExpertConsultationConfig> edit(ExpertConsultationConfigEditDto dto) {
        List<ExpertConsultationConfig> result = new ArrayList<ExpertConsultationConfig>();
        Integer expertId = dto.getExpertId();
        Optional<Expert> res = expertRepository.findById(expertId);
        if (!res.isPresent()) {
            throw new BadRequestException("专家未找到");
        }

        List<Integer> listsId = new ArrayList<Integer>();
        List<Integer> listsIdWithNoDelete = new ArrayList<Integer>();
        List<ExpertConfigListsDto> list = dto.getList();
        if (list != null && list.size() > 0) {
            for (ExpertConfigListsDto dto2 : list) {
                Integer id = dto2.getId();
                Optional<ExpertConsultationConfig> res2 = expertConsultationConfigRepository.findById(id);
                if (res2.isPresent()) {
                    ExpertConsultationConfig expertConsultationConfig = res2.get();
                    List<String> list1 = dto2.getList();
                    if (list1 != null && list1.size() > 0) {
                        expertConsultationConfig.setTimeSlot(list1.get(0) + ";" + list1.get(1));
                    }
                    expertConsultationConfig.setIsDelete(0);
                    expertConsultationConfigRepository.save(expertConsultationConfig);
                    listsId.add(id);
                } else {
                    //未找到表示新增
                    ExpertConsultationConfig expertConsultationConfig2 = new ExpertConsultationConfig();
                    expertConsultationConfig2.setId(id);
                    expertConsultationConfig2.setIsDelete(0);
                    expertConsultationConfig2.setExpertId(expertId);
                    List<String> list1 = dto2.getList();
                    if (list1 != null && list1.size() > 0) {
                        expertConsultationConfig2.setTimeSlot(list1.get(0) + ";" + list1.get(1));
                    }
                    expertConsultationConfigRepository.save(expertConsultationConfig2);
                }
            }
            List<ExpertConsultationConfig> listWithNoDelete = expertConsultationConfigRepository.findByExpertId(expertId);
            if (listWithNoDelete != null && listWithNoDelete.size() > 0) {
                for (ExpertConsultationConfig ex : listWithNoDelete) {
                    listsIdWithNoDelete.add(ex.getId());
                }
            }

            List<Integer> res1 = getDifferenceSet(listsIdWithNoDelete, listsId);
            if (res1 != null && res1.size() > 0) {
                for (Integer id : res1) {
                    Optional<ExpertConsultationConfig> res2 = expertConsultationConfigRepository.findById(id);
                    if (res2.isPresent()) {
                        ExpertConsultationConfig expertConsultationConfig = res2.get();
                        expertConsultationConfig.setIsDelete(1);
                        expertConsultationConfigRepository.save(expertConsultationConfig);
                    }
                }
            }
        }
        return result;
    }

    public List<Integer> getDifferenceSet(List<Integer> allList, List<Integer> list) {
        List<Integer> resultList = new ArrayList<>();
        Map<String, Integer> map = new HashMap<>();
        list.forEach(i2 -> {
            map.put(i2 + "", i2);
        });
        allList.forEach(i1 -> {
            Integer m = map.get(i1 + "");
            //如果为空，则证明list2中无该数据
            if (m == null) {
                resultList.add(i1);
            }
        });
        return resultList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ExpertConsultationConfig resources) {
        ExpertConsultationConfig expertConsultationConfig = expertConsultationConfigRepository.findById(resources.getId()).orElseGet(ExpertConsultationConfig::new);
        ValidationUtil.isNull(expertConsultationConfig.getId(), "ExpertConsultationConfig", "id", resources.getId());
        expertConsultationConfig.copy(resources);
        expertConsultationConfigRepository.save(expertConsultationConfig);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            Optional<ExpertConsultationConfig> res = expertConsultationConfigRepository.findById(id);
            if (res.isPresent()) {
                ExpertConsultationConfig expertConsultationConfig = res.get();
                expertConsultationConfig.setIsDelete(1);
                expertConsultationConfigRepository.save(expertConsultationConfig);
            }
            //expertConsultationConfigRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<ExpertConsultationConfigDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ExpertConsultationConfigDto expertConsultationConfig : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("专家id", expertConsultationConfig.getExpertId());
            map.put("时间段", expertConsultationConfig.getTimeSlot());
            //map.put("排序", expertConsultationConfig.getSort());
            //map.put("h5 小程序 是否展示 默认展示", expertConsultationConfig.getIsShow());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ExpertConsultationConfig> saveList(ExpertConsultationConfigEditDto dto) {
        List<ExpertConsultationConfig> result = new ArrayList<ExpertConsultationConfig>();
        List<Integer> ids = new ArrayList<Integer>();//存所有新增及编辑的ids
        List<Integer> idAlls = new ArrayList<Integer>();
        Integer expertId = dto.getExpertId();
        Optional<Expert> res = expertRepository.findById(expertId);
        if (!res.isPresent()) {
            throw new BadRequestException("专家未找到");
        }
        List<ExpertConfigListsDto> list = dto.getList();
        if (list != null && list.size() > 0) {
            for (ExpertConfigListsDto expertConfigListsDto : list) {
                Integer id = expertConfigListsDto.getId();
                List<String> list1 = expertConfigListsDto.getList();
                //TODO 如果此id为空则表示新增
                if (id == null) {
                    ExpertConsultationConfig expertConsultationConfig = new ExpertConsultationConfig();
                    expertConsultationConfig.setIsDelete(0);
                    expertConsultationConfig.setExpertId(expertId);
                    if (list1.size() == 2) {
                        expertConsultationConfig.setTimeSlot(list1.get(0) + ";" + list1.get(1));
                    }
                    ExpertConsultationConfig save = expertConsultationConfigRepository.save(expertConsultationConfig);
                    ids.add(save.getId());
                    result.add(save);
                } else {
                    Optional<ExpertConsultationConfig> ops = expertConsultationConfigRepository.findById(id);
                    if (ops.isPresent()) {
                        //TODO 有的话编辑 没有的话继续新增 id填此id
                        ExpertConsultationConfig expertConsultationConfig = ops.get();
                        expertConsultationConfig.setTimeSlot(list1.get(0) + ";" + list1.get(1));
                        expertConsultationConfig.setExpertId(expertId);
                        expertConsultationConfig.setIsDelete(0);
                        ExpertConsultationConfig save = expertConsultationConfigRepository.save(expertConsultationConfig);
                        ids.add(save.getId());
                        result.add(save);
                    } else {
                        ExpertConsultationConfig expertConsultationConfig = new ExpertConsultationConfig();
                        expertConsultationConfig.setTimeSlot(list1.get(0) + ";" + list1.get(1));
                        expertConsultationConfig.setExpertId(expertId);
                        expertConsultationConfig.setId(id);
                        expertConsultationConfig.setIsDelete(0);
                        ExpertConsultationConfig save = expertConsultationConfigRepository.save(expertConsultationConfig);
                        ids.add(save.getId());
                        result.add(save);
                    }
                }
            }
            List<ExpertConsultationConfig> resList = expertConsultationConfigRepository.findByExpertId(expertId);
            if (resList != null && resList.size() > 0) {
                for (ExpertConsultationConfig expertConsultationConfig : resList) {
                    idAlls.add(expertConsultationConfig.getId());
                }
                if (idAlls.size() > ids.size()) {
                    //TODO 多余的全部设为删除状态
                    List<Integer> differenceSet = getDifferenceSet(idAlls, ids);
                    if (differenceSet != null && differenceSet.size() > 0) {
                        for (Integer id : differenceSet) {
                            Optional<ExpertConsultationConfig> res2 = expertConsultationConfigRepository.findById(id);
                            if (res2.isPresent()) {
                                ExpertConsultationConfig expertConsultationConfig = res2.get();
                                expertConsultationConfig.setIsDelete(1);
                                expertConsultationConfigRepository.save(expertConsultationConfig);
                            }
                        }
                    }
                }
            }
        }else {
            //TODO则删除原有时间段配置
            List<ExpertConsultationConfig> resList = expertConsultationConfigRepository.findByExpertId(expertId);
            if (resList != null && resList.size() > 0) {
                for (ExpertConsultationConfig expertConsultationConfig : resList) {
                    Integer id = expertConsultationConfig.getId();
                    Optional<ExpertConsultationConfig> res2 = expertConsultationConfigRepository.findById(id);
                    if (res2.isPresent()) {
                        ExpertConsultationConfig expertConsultationConfig2 = res2.get();
                        expertConsultationConfig2.setIsDelete(1);
                        expertConsultationConfigRepository.save(expertConsultationConfig2);
                    }
                }
            }
        }
        return result;
    }
}